package impl

import (
	"context"
	"strconv"

	"gitee.com/liuxiaowei123/vblog-1.1/app/token"
	"gitee.com/liuxiaowei123/vblog-1.1/app/user"
	userimpl "gitee.com/liuxiaowei123/vblog-1.1/app/user/impl"
	"gitee.com/liuxiaowei123/vblog-1.1/config"
	"gitee.com/liuxiaowei123/vblog-1.1/exception"
	"gitee.com/liuxiaowei123/vblog-1.1/ioc"
	"gorm.io/gorm"
)

const AppName = "TokneController"

var _ token.TokenService = &TokenServiceImpl{}

func init() {
	ioc.IocController().Registry(&TokenServiceImpl{})
}

type TokenServiceImpl struct {
	db      gorm.DB
	usersvc user.UserService
}

func (t *TokenServiceImpl) Init() {
	t.db = *config.C.Mysql.Getconn().Debug()
	t.usersvc = ioc.IocController().Get(userimpl.AppName).(user.UserService)
}

func (u *TokenServiceImpl) Name() string {
	return AppName
}

func NewTokenServiceImpl(userimpl user.UserService) *TokenServiceImpl {
	return &TokenServiceImpl{
		db:      *config.C.Mysql.Getconn().Debug(),
		usersvc: userimpl,
	}
}

func (t *TokenServiceImpl) Login(c context.Context, req *token.LoginRequest) (*token.Token, error) {
	// 查询用户
	r := user.NewDescribeUserRequestByUsername(req.Username)
	u, err := t.usersvc.DescribeUser(c, r)

	if err != nil {
		return nil, exception.NewNotfound("没有%s用户", req.Username)
	}
	// 比对密码
	err = u.CompareHash(req.Password)
	if err != nil {
		return nil, exception.NewAuthfailed("用户：%s验证失败", req.Username)
	}

	// 颁发token
	tk := token.NewToken()
	tk.UserName = u.UserName
	// 没有加 tk.UserId = u.ID ，导致UserId=0,而查询不到用户，导致报错
	tk.UserId = u.ID

	// 存入token
	err = t.db.WithContext(c).Create(tk).Error
	if err != nil {
		return nil, err
	}

	return tk, nil
}

func (t *TokenServiceImpl) Logout(c context.Context, req *token.LogoutRequest) error {
	return nil
}

func (t *TokenServiceImpl) ValiateToken(c context.Context, req *token.ValiateTokenRequest) (
	*token.Token, error) {
	// 判断传入的token是否存在
	tk := token.NewToken()
	err := t.db.WithContext(c).Where("access_token = ?", req.AccessToken).First(tk).Error
	if err != nil {
		return nil, exception.NewNotfound("查不到此token")
	}

	// token是否合法
	err = tk.IsExpired()
	if err != nil {
		return nil, err
	}

	// 给token上下文中，补充role信息
	u := user.NewDescribeUserRequestById(strconv.Itoa(tk.UserId))
	// u := user.NewDescribeUserRequestByUsername(tk.UserName)
	// fmt.Println(tk.UserId)
	us, err := t.usersvc.DescribeUser(c, u)
	if err != nil {
		return nil, err
	}
	tk.Role = us.Role
	return tk, nil
}
